﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "ProcessCommandUtil.h"
#include "ICommand.h"
#include "UpdateCtrlStatusEvent.h"
#include "ICommandManager.h"
#include "JournalUtils.h"
#include "IJournalCommandData.h"
#include "IActionManager.h"
#include "IApplication.h"
#include "IUiDocumentViewManager.h"
#include "IMainWindow.h"
#include "IUiView.h"
#include "IAction.h"
#include "CommandParameters.h"
#include <QAction>
#include <QApplication>
#include <QMenu>
#include <qevent.h>

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

namespace gcmp
{
    class CommandResourceHandler
    {
    public:
        CommandResourceHandler(const QObject* pObject) : m_isNeedReturn(false)
        {
            const QAction *pAction = dynamic_cast<const QAction*>(pObject);
            if (pAction && !m_sIsCommandExecuted)
            {
                //退出之前的命令
                IActionManager::Reset();
                m_spAction = const_cast<QAction*>(pAction);
                m_isNeedReturn = true;
            }
            m_sIsCommandExecuted = false;
        }

        bool IsNeedReturn() const 
        {
            return m_isNeedReturn;
        }

        static bool IsCommandExecuted()
        {
            return m_sIsCommandExecuted;
        }

        static void ExecuteCommand()
        {
            if (m_spAction)
            {
                QPoint point(1, 1);
                //如果命令没有执行完成，需要先退出上一个命令，再执行此命令
                QWidget* pWidget = m_spAction->parentWidget();
                QMenu* pMenu = dynamic_cast<QMenu*>(pWidget);
                //如果命令里的实现逻辑使用到了消息循环机制阻塞UI线程（如：InteractivePicker），需要先终止上一个命令，再启用新的命令
                //启用新的命令采用模拟用户点击按钮的qt事件
                //CheckBox和RadioButton等状态控件不会绑定命令，或者命令中一般不会使用阻塞机制，不需要处理
                if (pMenu)
                {
                    QRect rect = pMenu->actionGeometry(m_spAction);
                    point = rect.center();
                    pWidget = pMenu;
                }
                if (pWidget)
                {
                    QEvent *pMousePressEvent = NEW_AS_QT(QMouseEvent, QEvent::MouseButtonPress, point, Qt::MouseButton::LeftButton,
                        Qt::MouseButton::LeftButton, Qt::NoModifier);
                    QApplication::postEvent(pWidget, pMousePressEvent);

                    QEvent *pReleaseEvent = NEW_AS_QT(QMouseEvent, QEvent::MouseButtonRelease, point, Qt::MouseButton::LeftButton,
                        Qt::MouseButton::LeftButton, Qt::NoModifier);
                    QApplication::postEvent(pWidget, pReleaseEvent);
                }
                m_spAction = nullptr;
            }
        }

        ~CommandResourceHandler()
        {
            m_sIsCommandExecuted = true;
        }
    private:
        static bool m_sIsCommandExecuted;
        static QAction *m_spAction;
        bool m_isNeedReturn;
    };
    bool CommandResourceHandler::m_sIsCommandExecuted = true; //命令是否已经执行完成
    QAction* CommandResourceHandler::m_spAction = nullptr;

void ProcessCommandUtil::ProcessRibbonBarCommand(const std::wstring& commandId, const gcmp::CommandParameters& commandParameters, const QObject* pSender)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pSender, L"pSender为空",L"GDMPLab",L"2024-03-30");
    CommandResourceHandler commandResourceHandler(pSender);
    if (commandResourceHandler.IsNeedReturn())
    {
        return;
    }
    //需要更改
    //ContextualPageCommandExecutionFlag contextualPageCommandExecutionFlag(IsSenderFromContextualPage(pSender));
    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr, L"pUiViewMgr为空",L"GDMPLab",L"2024-03-30");

    ICommandManager* pCmdMgr = ICommandManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr, L"pCmdMgr为空",L"GDMPLab",L"2024-03-30");

    ICommand* pCommand = pCmdMgr->GetCommand(commandId);
    if (pCommand != nullptr)
    {
        if (pCommand->HasCommandData())
        {
//             OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA);
//             DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"GDMPLab", L"2023-12-20");
//             opJournalCmdData->SetCommandName(pCommand->GetCommandId());
//             JournalUtils::StartRecordCommand(TransferOwnership(opJournalCmdData));
            pCmdMgr->SendCommand(commandId, true);
        }
        else
        {
            OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
            DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针",L"GDMPLab",L"2024-03-30");
            opJournalCmdData->SetCommandName(pCommand->GetCommandId());
            opJournalCmdData->SetParameterArray(commandParameters);
            JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));
            pCmdMgr->SendCommand(commandId, commandParameters);
        }
        //ActionManager::ProcessCommand(pUiDocViewMgr->GetCurrentUiView(), pCommand, commandParameters);
    }
    else
    {
        DBG_WARN(L"无法找到字符串对应的注册命令：" + commandId,L"GDMPLab",L"2024-03-30");
    }

    // 设置默认光标。
    IAction* pCurrentAction = IActionManager::CurrentAction();
    if (pCurrentAction)
    {
        if (IUiView* pCurrentView = pUiDocViewMgr->GetCurrentUiView())
            pCurrentView->SetCursorPath(pCurrentAction->GetCursorPath());
    }

    // 刷新界面。
    gcmp::OwnerPtr<UpdateCtrlStatusEvent> pEvent = NEW_AS_OWNER_PTR(UpdateCtrlStatusEvent);
   /* IMainWindow* pMainWindow = IMainWindow::GetMainWindow();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pMainWindow, L"pMainWindowPrivate为空",L"GDMPLab",L"2024-03-30");
    pMainWindow->PostEvent(TransferOwnership(pEvent));*/
    IApplication::Get()->PostEvent(TransferOwnership(pEvent));
    CommandResourceHandler::ExecuteCommand();
}

void ProcessCommandUtil::ProcessStatusBarCommand(const std::wstring& commandId, const gcmp::CommandParameters& commandParameters, const QObject* pSender)
{
    CommandResourceHandler commandResourceHandler(pSender);
    if (commandResourceHandler.IsNeedReturn())
    {
        return;
    }

    ICommandManager* pCmdMgr = ICommandManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr, L"pCmdMgr为空",L"GDMPLab",L"2024-03-30");

    ICommand* pCommand = pCmdMgr->GetCommand(commandId);
    if (pCommand != nullptr)
    {
        gcmp::CommandParameters cmdParams;
        if (pCommand->HasCommandData())
        {
//             OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA);
//             DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"GDMPLab", L"2023-12-20");
//             opJournalCmdData->SetCommandName(pCommand->GetCommandId());
            pCmdMgr->SendCommand(commandId, true);

        }
        else
        {
            OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
            DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针",L"GDMPLab",L"2024-03-30");
            opJournalCmdData->SetCommandName(pCommand->GetCommandId());
            opJournalCmdData->SetParameterArray(cmdParams);
            JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));
            pCmdMgr->SendCommand(commandId, cmdParams);
        }
    }
    else
    {
        DBG_WARN(L"无法找到字符串对应的注册命令：" + commandId,L"GDMPLab",L"2024-03-30");
    }

    IMainWindow* pUIMainWnd = IMainWindow::GetMainWindow();

    // 刷新界面。
    gcmp::OwnerPtr<UpdateCtrlStatusEvent> pEvent = NEW_AS_OWNER_PTR(UpdateCtrlStatusEvent);
    //IMainWindow* pMainWindow = IMainWindow::GetMainWindow();
    //DBG_WARN_AND_RETURN_VOID_UNLESS(pMainWindow, L"pMainWindowPrivate为空", L"GDMPLab", L"2023-12-20");
    //pMainWindow->PostEvent(TransferOwnership(pEvent));
    IApplication::Get()->PostEvent(TransferOwnership(pEvent));
    CommandResourceHandler::ExecuteCommand();
}

bool ProcessCommandUtil::IsLastCommandExecuted()
{
    return  CommandResourceHandler::IsCommandExecuted();
}

}
